/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tuplestoremasterserver;

import core.IServerCallBack;
import core.ProtocolSD;
import core.ProtocolSD.Operation;
import core.ServerCallBack;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import logging.LOG;
import protocol.TSFileTag;
import protocol.TSServerInfo;

/**
 *
 * @author Jorge
 */
public class ClientListener implements ProtocolSD.IProtocolListener{

    private Operation operation;

    private List<Integer> currentKeys;

    private Map<Integer,Integer> keysSizes ;

    private boolean close=false;
    

    public void onReadHeader(int operation, int numArgs, ProtocolSD protocolSD) {
        this.operation = Operation.values()[operation];
        LOG.append("Recebido Pedido de "+this.operation.name());
        if(this.operation==Operation.GET){
            this.currentKeys= new ArrayList<Integer>(numArgs);
        }else{
            this.keysSizes = new HashMap<Integer, Integer>(numArgs);
        }
    }

    public void handlePut(byte [] data){
        keysSizes.put(ProtocolSD.byteArrayToInt(data, 0),ProtocolSD.byteArrayToInt(data,4));
    }

    public void handleGet(byte [] data){
        currentKeys.add(ProtocolSD.byteArrayToInt(data, 0));
    }

    public void onReadArgument(byte[] data, ProtocolSD protocolSD) {
        switch(operation){
            case GET : handleGet(data);break;
            case PUT_KEYS : handlePut(data);break;
        }
    }

    public void onReadArgumentSize(int size,  ProtocolSD protocolSD) {
        
    }

    public void handlerFinishGet(ProtocolSD protocolSD){
        List<String> list = new ArrayList<String>();
        for(Integer i : this.currentKeys){
            TSServerInfo server = MasterServer.getServerOfKey(i);
            if(server!=null){
                list.add(server.getConnectionString()+"/"+i);
            }
        }
        protocolSD.writeStrings((byte)Operation.REDIRECT_READ.ordinal(),list);
    }

    public void handlerFinishPut(ProtocolSD protocolSD){
        List<String> list = new ArrayList<String>();
        for(Map.Entry<Integer,Integer> entry : this.keysSizes.entrySet()){
            TSServerInfo server = MasterServer.getBestFit(entry.getKey(), entry.getValue());
            if(server!=null){
                list.add(server.getConnectionString()+"/"+entry.getKey());
            }
        }
        protocolSD.writeStrings((byte)Operation.REDIRECT_WRITE.ordinal(),list);
    }

    public void onReadAllArguments(ProtocolSD protocolSD) {
        protocolSD.getKey().interestOps(SelectionKey.OP_WRITE);
        switch(operation){
            case GET : handlerFinishGet(protocolSD);break;
            case PUT_KEYS : handlerFinishPut(protocolSD);break;
        }
    }
    public void setCallBack(IServerCallBack callback) {
       
    }

    public IServerCallBack getCallBack() {
         return null;
    }

    public void onWriteComplete(ProtocolSD protocolSD) {
        protocolSD.getKey().interestOps(SelectionKey.OP_READ);
        close=true;
        try {
            protocolSD.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void onAcceptConnect() {

    }

    public void onReadParcialParam(byte[] readedBytes, int tmpParcial, int remaning,ProtocolSD protocolSD) {
        
    }

    public boolean isClose() {
        return close;
    }
}
